home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Mail / MailEnclosure / Source.v0.15 / ModuleMgr.m < prev    next >
Text File  |  1995-06-12  |  5KB  |  214 lines

  1. #import "ModuleMgr.h"
  2. #import "TokenString.h"
  3. #import "Directory.h"
  4. #import "NXGets.h"
  5.  
  6. @implementation ModuleMgr
  7.  
  8.  
  9. - initForPaths: (const char *)aPath fileType: (const char *)aType
  10. {
  11.    [super initKeyDesc: "*"];
  12.  
  13.    paths = [[StringStorage alloc] init: aPath];
  14.  
  15.    if(!*[paths stringValue])
  16.    {
  17.       [paths setStringValue: "/LocalLibrary/%s:~/Library/%s"];
  18.       [paths replaceSubstring: "%s" with: [NXApp appName]];
  19.       [paths replaceSubstring: "%s" with: [NXApp appName]];
  20.    }
  21.  
  22.    NXLogError("Looking for modules in %s", [paths stringValue]);
  23.    fileType = [[StringStorage alloc] init: aType];
  24.  
  25.    features = (Protocol *)0;
  26.    [self loadModules];
  27.  
  28.    return self;
  29. }
  30.  
  31. - setFeatures: (Protocol *) aProtocol
  32. {
  33.    features = aProtocol;
  34.    return self;
  35. }
  36.  
  37.  
  38. - loadModules
  39. {
  40.    int cnt;
  41.    const char *aPath;
  42.    id modules = [[Directory alloc] init];
  43.    id path = [[TokenString alloc] init: [paths stringValue]];
  44.    id pattern = [[StringStorage alloc] init: "*."];      
  45.  
  46.    [path setSeparator: ':'];
  47.    [pattern appendStringValue: [fileType stringValue]];
  48.  
  49.    while(aPath = [path popStringValue])
  50.    {
  51.       [modules setPath: aPath];
  52.  
  53.       if([modules count] && ( cnt = [modules select: [pattern stringValue]]))
  54.       {
  55.      int x;
  56.      id sendModules = [modules selectedFiles];
  57.      id modulePath;
  58.      char *moduleName;
  59.  
  60.      /*
  61.       * Create a hash of the modules. Use the name and path until the module is needed
  62.       * And the the path will be converted to a bundle.
  63.       */
  64.      for(x = 0; x < cnt; x++)
  65.      {
  66.         NX_MALLOC(moduleName, char,[[sendModules objectAt: x] count]);
  67.         strcpy(moduleName, [[sendModules objectAt: x] stringValue]);
  68.         modulePath = [[StringStorage alloc] init: [modules path]];
  69.         [modulePath appendCharValue: '/'];
  70.         [modulePath appendStringValue: moduleName];
  71.         moduleName[strlen(moduleName) - (strlen([fileType stringValue]) + 1)] = (char)0; /* clip off .sndO */
  72.         [self insertKey: moduleName value: modulePath];
  73.         if(![self isKey: moduleName])
  74.         NXLogError("Hash failed\n");
  75.      }
  76.       }
  77.    }
  78.    [pattern free];
  79.    [modules free];
  80.    [path free];
  81.    return self;
  82. }
  83.  
  84. - loadFileType: (const char *)aType
  85. {
  86.    return self;
  87. }
  88.  
  89. - free
  90. {
  91.    [paths free];
  92.    [fileType free];
  93.    return [super free];
  94. }
  95.  
  96.  
  97. - getModule: (const char *)moduleName
  98. {
  99.    id bundle = (id)[self valueForKey: moduleName];
  100.    id loaded, primeClass;
  101.    char modulePath[MAXPATHLEN];
  102.    char *newKey;
  103.    
  104.    if(!bundle)
  105.    {   
  106.       const char *aKey;
  107.  
  108.       [self initState]; 
  109.       
  110.       NXLogError("Could not find hash entry: (%s)\n", moduleName);
  111.       while (aKey = [self nextKey]);
  112.       NXLogError("moduleName: %s", aKey);
  113.  
  114.       return nil;
  115.    }
  116.    
  117.    if([bundle isKindOf: [NXBundle class]])
  118.        return bundle;
  119.  
  120.    if(![bundle isKindOf: [StringStorage class]])
  121.    {
  122.       NXLogError("Hash stored bad item...");
  123.       return nil;
  124.    }
  125.    
  126.    /* Bundle was not yet loaded - do so. */
  127.    NXLogError("Need to load: %s", [bundle stringValue]);
  128.  
  129.    loaded = [[NXBundle alloc] initForDirectory: [bundle stringValue]];
  130.  
  131.    if(!loaded)
  132.    {
  133.       NXLogError("failed to load\n");
  134.       return nil;
  135.    }
  136.       
  137.    /* insert the real bundle into the hash now to replace the place holder */
  138.    NX_MALLOC(newKey, char, strlen(moduleName));    /* allocate another key - this is a bug in HashTable I feel */
  139.    strcpy(newKey, moduleName);
  140.    [self insertKey: newKey value: loaded];
  141.  
  142.    [bundle free];                 /* free up the path/place holder */
  143.    bundle = loaded;
  144.  
  145.    /*
  146.     * Before we resolve the symbols in the bundle see if it needs any
  147.     * other bundles loaded as ancestors.
  148.     */
  149.    if([bundle getPath: modulePath forResource: "inheritance" ofType: ""])
  150.    {
  151.       NXStream *sp;
  152.       char parentsBuf[128];
  153.       const char *parent;
  154.       id parents;
  155.  
  156.       sp = NXMapFile(modulePath, NX_READONLY);
  157.  
  158.       if(!sp)
  159.       {
  160.      NXLogError("Couldn't open %s\n", [bundle stringValue]);
  161.      return nil;
  162.       }
  163.       NXGets(parentsBuf, 128, sp);
  164.       NXClose(sp);
  165.  
  166.                          /* Get known parrents and load them */
  167.       parents = [[TokenString alloc] init: parentsBuf];
  168.       while(parent = [parents popStringValue])
  169.       if(![self getModule: parent])
  170.       {
  171.          NXLogError("Ancestor failed to load...\n");
  172.          return nil;
  173.       }
  174.      
  175.       [parents free];
  176.    }
  177.  
  178.    if(!(primeClass = [bundle principalClass]))
  179.    {                         /* make rld resolve names */
  180.       NXLogError("Corruoted bundle: %s\n", moduleName);
  181.       return nil;
  182.    }
  183.  
  184.    if(features)
  185.    {
  186.       if(![primeClass conformsTo: features])    
  187.       {
  188.      NXLogError("Bundle's principal class does not conform to %s protocol.", [features name]);
  189.      return nil;
  190.       }
  191.    }
  192.  
  193.    return bundle;
  194. }
  195.  
  196. - (NXHashState) initState
  197. {
  198.    state = [super initState];    
  199.    return state;
  200. }
  201.  
  202. - (const char *)nextKey
  203. {
  204.    static const void  *key, *value; 
  205.  
  206.    if([self nextState: &state key: &key value: &value])
  207.        return (const char *)key;
  208.    else
  209.        return (const char *)0;
  210. }
  211.  
  212.  
  213. @end
  214.